perm filename PRIVRN.DOC[HAL,HE] blob sn#166301 filedate 1974-09-11 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00007 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	THIS FILE IS INTERNAL DOCUMENTATION NOT FOR PUBLICATION.
C00003 00003		DEVICES
C00013 00004		IMPLEMENTATION OF ON-MONITORS
C00016 00005		INTERPRETER CODE FOR MOTIONS
C00018 00006		THE INTERPRETER SCHEDULER
C00028 00007	SWING-TIME Calculation of set points.
C00030 ENDMK
C⊗;
THIS FILE IS INTERNAL DOCUMENTATION NOT FOR PUBLICATION.
Authors: RF and LOU.

	DEVICES

	One does not request that a joint or a screwdriver start up;
one requessts that a device be started.  A device has the following
format:
	JCOUNT	Number of joints in the device
	RCOUNT	Number of running joints at the moment
	JOINT 	Points to joint control block for one joint
	STATUS	Status of this joint.  Includes these bits:
	    STARTED	This joint has been started up
	    RUNNING	This joint currently in motion
	    TERMINATED  This joint finished normally
	    ERROR	This joint had an error condition
	    STOPPED	Someone had to stop this joint.
	These last two fields, JOINT and STATUS are repeated
	for each joint.

	A joint control block has these fields:
	THETA	Current joint angle
	TORQUE	Current torque
	DRIVE	Current drive
	TRAJ	Pointer to the trajectory currently being followed

The way that an interpreter is expected to accomplish a move is
as follows:

0)	Execute a "wait-enable" for each on-monitor which is
to run during the motion.  These monitors will be started up
at the time the motion proper starts.

1)	Execute the "prepare move" instruction, which points to
a trajectory file (to be described) and causes modifications to
be made.

2)	Set up a device which includes all the joints of interest.
Cause the device to begin executing.  All this is done with the
instruction "start move" which takes as argument a bit pattern
encoding the joints to include in the device.  Start move causes
the servos to be scheduled.
Note that "start move" acts logically very much like a sprout;
the coming wait instruction will wait on this device.

3)	Execute a "wait" instruction.
This causes all the prepared wait-type on-monitors to be started, and
the interpreter itself is put
in a wait state which will terminate when the device is finished.
All the on-montors active for the motion will also be disabled before
the interpreter is called back.




Termination  of a move is quite simple:  The joint status word, which
is global to the entire runtime, is just set for each joint  affected
to  a value  which  means "unrunnable"  The  next time  the servo  is
awakened,  it  will  notice  this   and  request  euthanasia.     The
termination also requires that the motors be  stopped, and the brakes
applied, and the resting point of the arm determined.  

Some care must be taken to prevent two interpreters proceeding at the
same time  under conditions whereby one should  really be waiting for
the other.    Specifically,  during  a  move,  the  interpreter  that
initiated that move is suspended until it is complete.  Therefore, if
an  on-test  causes  another  interpreter  to  start,  the  suspended
interpreter must remain suspended until the new one dies.
TRAJECTORY TABLES

The following are necessary properties of trajectory tables:
	Must state which frames are used, so the servo can do appropriate 
		update.
	Must be perspicuous enough to allow servo to find the things which
		it must update.
	Must allow escape to interpret mode at end of each segment for
		each joint, in order to initiate new motions or "on" tests.

	A trajectory table  is a set  of joint-segment tables.   Each
joint-segment table is intended to give instructions for the servoing
of one joint along one segment of  the path.  There are two types  of
such tables: location  and inertia.  The servo follows  each of these
simultaneously and asynchronously.


FORMAT OF THE  LOCATION-JOINT-SEGMENT TABLE: This table is  ten words
long.

words 1,2,3,4,5,6:  coefficients a5,a4,a3,a2,a1,a0 of the trajectory.
Polynomial is normalised for tε[0,1].

word 7: Duration of segment in milliseconds.

word 8: Pointer to next location-joint-segment table for  this joint.
If this is the last segment, word 8 is 0.

word  9: Pointer  to frame  which is  to be  assumed at  end of  this
segment.  If no particular frame, then this is  0.  This is used in a
preprocessing step to modify  the coefficients of the  polynomial; at
swing time it is not needed.

word 10:  If not 0,   then a  pointer to a  location of interpretable
code where an interpreter is to  be instantiated and begun.  This  is
for the THEN part of VIA lists.

FORMAT OF  THE INTERTIA-JOINT-SEGMENT TABLE:  This table  is 7  words
long.

words 1,2: Coefficients j1,j0 of joint inertia polynomial, normalized
for tε[0,1].

words  3,4:  Coefficients  g1,g0   of  gravity  loading   polynomial.
Likewise normalized.

word 5: Duration of segment in milliseconds.

word 6: Control word, with bits for free, force, drive, nodrive, etc.
see later  discussion on control words.  This is copied into a global
location at start of inertia-joint-segment.

word 7: Pointer to next intertia-joint-segment table  for this joint.
If this is the last segment, word 7 is 0.


GO TABLES

The following are necessary properties of go tables:
	Must state list of frames to use (including initial deproach
and via-list)
	Must allow escape to interpret mode at end of each segment.

	A GO table is a list of frames through which the motion is to
proceed.  Each is specified by its address.  The first one is the deproach
of the start frame; the penultimate is the deproach of the final
frame.  Following each frame address is an interpreter address, which
is the adrress of the interpreter (if any) to be invoked upon achievement
of the preceeding frame.  The last frame is distinguished by an interpreter
address of -1.
	IMPLEMENTATION OF ON-MONITORS
This page is a set of notes for the eventual documentation.
Author:  RF

	The code for an on-monitor is in-line and jumped around.
The code is PDP11 code, including calls on arithmetic subroutines,
if neccessary.

Each on-monitor is given a unique name by the compiler.
The scheduler associates that name with the location of the
enable bit for this monitor.

On-monitors have only two states:  enabled and disabled.
There is a status word associated with each on-monitor;
it contains two bits:  the enabled, and the kill.

At the start of a program, all on-monitors are disabled.
That means enable=0, kill=0.

At the end of a block, the compiler includes code to disable all
on-monitors within that block.

Only one copy of an on-monitor ever exists.  No multiple instantiations.

ENABLE <NAME>
To enable a software monitor, 
tell kernel to activate it at its address, in on-level, where
it will have PDP11 code to:
1) look at its "enabled bit".  If already on, dismiss. If not, turn on.
2) clear all its working buffers (if any) 
3) schedule its second entry (the monitor itself) to be awakened at
the appropriate intervals.  Then dismiss.

The software monitor, every time it is awakened, does the following:
1)  look at its "kill bit".  If on, clear and dismiss.
2)  execute the code for its check.
3)  if condition satisfied, do immediate stuff,
 instantiate the conclusion, and dismiss.
4)  reschedule self at appropriate interval.  Dismiss.

To enable a hardware monitor,
tell kernel to activate it at its address, in on-level, where
it will have PDP11 code to:
1)  look at the device enabled bit.  If already on, return.  If not, turn on.
2)  dismip↓x~p4(4T"&Nε∀b∃↓rt
6∃xhRS=β&KOπf)β¬β≡{≠S←∂∪∃β7}s'S?∩aβO↔"β'SMα↓/'faβ'"⊃84*&yβ∪'≡3∃ε	β#π⊗#←πK*β7?;O#?I1ε≠3↔π∩β'SMα∪↔;π⊗c↔⊃β⊗KQ	8hP0&&u"⊗JB∀*R⊗I∧~>∩∃∧2>IαlzR&>u_4+;␈!βg↔"βK↔π'I9↓α∂+S#?∪Q↓αJ2p4(4U##∃β≡{∪∃β>+;↔K∂#↔⊃β6{Iβ¬εk?[∃εK;∂3.#↔Mβ&C∃β≠}c3?←Ns≥β'w#↔KC⊗+S↔Iε≠?77∞s∪MhhP4)EJαCK↔εK∃βn{[∃9ααS#'~βC?'w#MβSzβS#∃εk?[∃π#π3*aβπ;"β∂πW≡+MβSF)βSK∞S↔∂S␈∪d4+&yβ∃εk?∪'6K↔⊃β&yβ∂?v3?K5π#=β∂/∪K↔;"β3?∂∂#'?;~β?→β6K¬βC}K;SMr↓α+?NsP4+f{π∪'v9β'Mε≠π3∂.cπS↔"β≠?Iε+π∂!π3'¬βε{';QεMβ←.c184Ph)I%∧+;πf)β?9nk?;'&{I9↓¬##↔K*β7πeε∪∃β7␈∪∃βSF9β?v)β?→π##↔O*β';O'∪W∂SN{;M8hP4)MJαOSπ↔!β7?&K?99ααS#'~βC?'w#MβSzβS#∃εk?∪'6K↔⊃βn{[∃β&3∃ph(4)"Iαπ←∞KQβ∂}kC3↔&K?99ααS#'~β∂πW≡+MβSF)β';&+KCK/#↔Iβ&yβ←πO!βW;&K1βSF(4+7␈3∃β#∂→β∂?oβ3↔S.!1β?∩βS#∃εK5βFMβ.+9βO&{CC↔"β≠?Iπ≠?7∃π∪↔πO}q84*&C∃βON;;π1π;#'∂Bβπ←π↑+MβSF)β';&+KCK/#↔Iβ≡{7↔Mε3K?5π;#'∂F+[↔IεS?'; h+O↔↔3=β≠Ns'O#/→β3π∨!iβ↔∞≠!βO/∪[=1εMβ'"β≠';O≠#↔Mbβ∂#↔≡[MβSzβO↔∃εK→βπf`4+SF)β?SF+KMβ∂∪∃β∪}s∃1β∞s⊃β'2βO=1ε←π//→βS#*β';S/∪CK↔&+Iβπ"βO↔K6yβ3↔6+184Ph)U%ε#'Oπ⊗c∃βπfaβ?9nk?;'&{KMβ∂≠O?∂NS↔⊃π;'S!εk?[∃r↓αS#O→β'Mε#?;∃εP4+≡+K[=εc↔[↔`h(4)2Iβ∪'≡k'OMπ#=β'w#↔KC⊗+S↔Iεc↔[↔bp4(4T3?K5ε{→βS⊗+↔∂&{Keβ␈+SCW"βS=↓	h4(hRRJεT*∞R>∃H4(&Tz&:Q∧b&NPhP&:Vl∩⊗Iα≤*≡L4PJZ&¬∧b&NPhP4**|J:P4PJ*>&u!α∩JM2∃α
dz∞,4PJ:⊗b h(&N,:6⊗:"α2&N h(4*≤*≡6⊗u $4(L→@4(L→D4(L→H4(L→L4(L→P4(Lr⊗bPhP4*ZLλ4(&5∩ε6∀hP&∩V∀
R&>ph(&:-BP4(LJ:R⊗∃αJ⊗R-⊂4(4P0&RD)α&:$*JBJ-"⊗Iα≤~"⊗∩,b⊗H4Ph(&'w#↔KC⊗+S↔K~βπK∃εkπ;π>+⊃βJβS#∃ε3?33␈;';≥π≠↔Qβ}1βK?/#';↔_h+←#N≠!βSF+eβ∂∞qβ∂πfa9↓α&C↔O∃π∪?WSNs↔Mβπ∪?['&)β¬β6∂'3O#eβ≠␈⊂4+Oπ∪?WSNs≥β;/9β';&+KCK/#↔KMbβ↔;S/∪';≥ε	β←πO!βOS∂#∃βWw#'1β∞c04+&+O∂↔v#↔;S~β#π[*βS↔KnK;πS.!1βπv!βS↔⊗k';π&K;≥9αα≠WK&C↔K7␈∪∃04VK;S↔↔βK↔S/∪Mβ∂∞qβGW/+∃α>rk7?;O#?KMπ#=β*βKW9ε#WK'v9βS#(h+;↔G!β←πO!9↓α∨#π;∪∂∪⊃α>rk7?;O#?KMαCS#?≡)β←#N≠!βπ⊗)β';&+;∪↔ h+S=ε∪∃βK.qβ∪W⊗K;≥β>/';:β3'≠*IβπK*βSK↔∂#↔⊃β&KK↔∂&ce1β∞s⊃β;␈ 4+JβS#↔≡)βK?/#';↔~q↓α'"β'Mβ&C∃βK/≠C?;≡K'3O#eβ?2β↔π∂BβCK?≡+OL4W#=β∪O≠π3*βπ31∧z977}s'S?↔→β?→π##∃β>/';:β[πKN+Seβ∂→β3}≠/L4VK∃β/C'S↔#YβS#O→β'Mε∪↔g?v!βS#*βK↔πfiβ?→π##∃β6{33?>K;≥β⊗{WS'v+M84PJ';S/∪CK↔&+KMβ↔+9βπ"βCK?≡+OO?∩β3↔[.a↓EβNqβOWε+K['≡{Iβ7}#∃84U≠CK?/#';≥ε	β;↔:β';S/∪CK↔&+Iβ'~β↔GWO3π3↔w!βS=πW↔WNs≥β'"β'9β&C∀4+f+[↔1β	βGW/+∃mβ&+K7'vS';:β'Mβ/W'[∞c↔;Qπ#=β∪O≠7'O≡K;≥9ααS#∃εc↔[↔b↓D4+NsS↔K↔+CQβF;∪3/⊃βWC}qβπ←∞[↔;'v9βK↔n{[↔Mπ##∃βπ∪?∂↔∨→βπQπ##∃βF+π⊂4V{→βSF)βGW/+∃1β∞s⊃β↔6+9β'2βS#∃πW↔W*β'Mβv{Qβ↔oβSe1εc↔π[/→βS#*β';S/∪KWC h+O↔"q↓αSFKMβ7∂IβO?.s⊃β←⊗{;≥1ε∪WQβO!β#π~βS#∃ε+≠≠↔∨!βS#∂!βπ9ε∂S'6(4+'w#↔KC⊗+S↔Iπ;'31εs↔[↔∩β∃βNsS↔K↔+CS↔"βeβ∞s?S#/⊃β';&+KCK/#↔I9αα'_4W##∃βNsS↔K↔+CQβF;∪3/⊃β≠'v#Mβ;␈##';:βS=β&yβπQε311π##↔9ε;⊃β}s3d4W##↔9ε#?↔MεKQβ∂f+πIβ&C∃β'w#↔KK/βQ9↓∧KQβ+.kCMβ&KK↔∂&ceβSzβS#∀hS';S/∪CK↔&+Iβ←FK∂!β>MβK.k?[↔"β≠K?jβS#∃πW↔W*p4(&&C∃β?vceβ∂.k↔K≡{7∃β6+πSW⊗)β'Mε+;S↔⊗K;≥β>'Q9ααπ30hSOSπ≡Yβ';6{K7π&K?9βO→β∂?εK↔⊃βNsS=β
βOπ≠*βC3π≡)1βπfaβ←πO!7Sgε(4+?rk7?;O#?KMεK∃β∞≠S'[∂#↔⊃9αα↔π∂BβS'7*β¬βC⊗{∂↔O~βS↔KnK;πS/→04+O!β'Mεs↔∂↔∨≠πKeπ#=βO.)β'→π##∃βn{S#↔∩β∂π9ε∪∃βπ⊗{WO↔"β≠K?jβ#↔HhSO3↔/↓9↓α>C↔9β6K;π3gIβO#*β←π//→βWAbβπ31εC↔Iβ>'Q7n{;'S␈∪Mβ7/≠P4+⊗)β∪'≡3↔"p4(4U∩∞2ε≥→α>:L!↓"&u"⊗≡⊗∩αNRε%*M1α⎇α
mα∃αRI↓Dz:&⊃Jα:⊗b"Il4(L~>66,rQi↓¬~RεR-→β#?f#MβSF)α/'faβπ;"α↔;π⊗c∃βO#M84PJ>B
εKMβSF)α?9oβK?∨⊗5β∂␈+;S↔∩p4(&t*bQβO→βWO.!β≠?∩β∂#πNs';≥ε{→β?w→l4(hRJ∞2
~MαB∀z∞⊗N≤J⊃↓"LrR⊗≡-⊃αB
bα∩⊗B,r∩⊗:%→1α↑JRRf∧)m↓hP&JB%⊃"BJ|~⊗NNL!%α:-BQ1αlzR"⊗∪YαJB%⊃">:L!%α↑JR>:~Il4(L~>66,rQi↓¬α
wC⊗{∨Kπjβ∂?Ww#↔I9αα∩⊗B,r∩⊗:%→w∂?.sQ84PJ↑ε&%"fB∃k↓β≠?∩βKW9b↓Eβ≠␈⊃β∪↔ε+;∪↔w!β←πO!1↓Iε3?Iβ/3↔;Qπ;π'Qph(&:-BQβW≡+⊃β≠␈⊃βGW/+';≥r↓α6>$B⊗Iβε{';S~βS=βn{S#↔∩p4(&<
&R>u→β'Mεc'OQε{→β∪/β↔;∪.sQβ?rk7?;O#?KMε∂S'6)β?;gIβ∪W⊗K;≥β>'QlhP4*J≤bεNM¬
V⊗V*↓"JB%⊃"BJ|~⊗NNL!%α",
⊃1α$
&1%Xh*JB%⊃↓"B∀z∞⊗N≤J⊃%α≥*JJ⊗u!l4*∃αRI"
*⊗V∃JαJV:
*⊗V∃Xh*∩⊗4J:∃α,rε
2*↓u↓	;		l4T"⊗~&t)α.&da↓u↓∩9I	lhP4*B∀z∞⊗∩-∩∃α&tJR&εdJj∃lhP&
⊗<J84(L≠?77.sQi↓∧+OSπ⊗c'O!πW↔W*β≠?Iεc↔[↔b↓El4PJFV⊗,)j"⊗!"JVu
V⊗V*Iα⎇αt*\bJ,~>J⊃αBBJ>≤*NN&"Il4(L≠?77.sQi↓∧+OSπ⊗c'O!ε{;'⊃?→β≠?∩β↔π∂Bβ?97n{;'S␈⊃l4(L2>J⊗~!α>rj6>:M">Iα$x4($L∩⊗≡&ph($&Bα⎇α:-8bJ⊗≤zJ⊃↓Dz:&⊃KX4($Lz:&⊃Tr⊗bQEA%α⎇¬∩:V2cX4($Lz:&⊃U~RεR-→"a%¬y↓AlhP$&>tJ⊃j>∧→"a%¬yα>B≠X4($L*:⊃lhP&⊗:#X4(4UαJ>∞,"VJ∃∧*:FV-*∃"J¬"I"F,*V∃%¬:"⊗J+YαJB%⊃"BJ|~⊗NNL!%α:-9%l4PJ
⊗≡Lp4(&≤z66⊗u!i↓απ+SMβ
βCK?≡+OMβ}qβ¬β∂+↔W∃r↓αFV-*∃βS.c3Mβ>C'∂ hP$'G.+W∃9αα:⊗]εKMβSF)βCK}≠↔OMεK⊃l4PJFV⊗,)jRεLa"↑"-∩∃%αzαBJ>≤*NN&#R:⊗b"BFV⊗,)jRεLa"↑"-∩∃%%¬yα:⊗;X4(&¬∩>∞⊗≥~&⊃jt*bQ"
*⊗V∃U"ε&1E:"⊗J*I%α⎇∧rV21Xh(&⊗t!l4(hRJBR∩BBJ>≤*NN&"IαBJ|~⊗∩V∀)α∩⊗
*⊗V∃αBJBR∩BFV⊗,)%α↑D*J∃%Xh(&
,:&84PJ∞>6l*:QiααK↔S/∪;MβF+π⊃β}1βGW/+∃1β>C'∂!εKMβK.k?[↔#X4(&∃αRI"¬∩>∞⊗≥~&⊃%∧
:N↑-⊃l4(LJ→αF,*V∃jD*ε⊃"<B⊗J∃J↓uαF,*V∃j$
&1"<B⊗J∃J4(&$B⊗8&∀*RVJrB:V2bIm↓α≤z66⊗u!i↓α.kCSeπW↔W+X4(&rN↑⊗∩α⎇αB∀z∞⊗N≤J⊃j:-BQ"F,*V∃jD*ε⊃"<B⊗J∃JIl4(LJ→↓"¬∩>∞⊗≥~&⊃jt*bQ"
*⊗V∃TB⊗ε⊃E:"⊗J*I%α⎇¬αJ>∞-~N&⊃Tr⊗bQD
:N↑-⊃%%↓jα:V2`h(&RD*8&F,*V∃j$
&1"<B⊗J∃Jα⎇αF,*V∃jD*ε⊃"<B⊗J∃KX4(&∀*RVJrBε:N<*I%lhP&⊗:#X4(4UαJ>∞,"VJ∃¬~BJ>-!↓"&∧→%l4PJ
⊗≡Lp4(&≤z66⊗u!iα&∧→β'Mπ##∃βNsS↔Kπ∪↔S↔∩βCK??∪π5β≡{W;S/⊃84(M##∃β.3≠↔∂"β'Mβ&yβCW"βS#∃εs↔]βNsS↔Kπ∪↔S↔∩β'9β&C∃βK.q7GW/+∃l4PJJBR∩↓"BJ|~⊗NNL!%α:-9l4(Lr⊗]αzα:⊗\E∩⊗∞>∀!↓"B∀z∞⊗N≤J⊃%lhP&BJ|~⊗NNL!jB
Dr⊗]%¬yα&B≠X4(&¬∩>∞⊗≥~&⊃j$*B⊗:$*:RMDr⊗]%¬y↓AlhP&BJ|~⊗NNL!j↑εM"RfB*B:⊗]Jα⎇↓AXh(&B∀z∞⊗N≤J⊃j6⎇""⊗IDr⊗]%¬yα∞V∃∩⊗:QXh(&B∀z∞⊗N≤J⊃j∩-α⊗:∩,rRM"≥*JJ⊗u!%α⎇¬αJ>∞-~N&⊃T"⊗B⊗t"⊗:R~B∞VJ∀*:Q%αY↓D4PJ⊗:F,*V∃"∃*:FV-*∃2:-9%l4PIr≡⊗t*JεR*α2⊗Z,a↓EαLrR⊗J∃*BQyXh(&⊗t!l4(hRBJ>≤*∩VJ*αR⊗JlJ:εR+X4(&∀*≡&9αα∞>6l*:QiααS↔KnK;πS/→βS#*β∂π3f+Il4PJJBR∩BBJ>≤*NN&"Iα6>kX4(&∃αRI"|r&⊃%¬2&∞RLi1α>d!l4(LJ:R⊗<*IαR,jAl4PJ&→α¬∩>∞⊗≥~&⊃j$*B⊗:$*:RMD~VJJ,rQ%Z↓@4(M""⊗9J
⊗≡Lq↓α∞|j6⊗:#Q↓αSFKMβOF{W3⊃εs↔[↔∩β#πCε+9l4PH&⊗J∀zI!
~R&Z*αBJ>≤*NMα$*B⊗:%→α>9∧∩2>∞Zα
⊗&t9α⊗bM"⊗⊃	KX4($M:ε&QXh($&,r⊃l4PJ6>5¬yαBJ|~⊗NNL!j6>$B⊗I"≥*JJ⊗u!%l4PJR⊗6αα⎇αB∀z∞⊗N≤J⊃j∩-α⊗:∩,rRM"lz5%αzαBJ>≤*NN&#R∩⊗B,r⊗:R~B6>5J↓5↓EXh(&&2αBJ>≤*NN&#R↑ε&%"fB∃Dj>5%k	αε:"αR⊗6βi@4(M""⊗8L∩⊗≡&r↓α∞>lj⊗:QR↓α7W∨!βπ←∞[↔9βn{5l4PH&Z&≥"&5αzαBJ>≤*NN&#R↑ε&$z:M"lz5%lhP$&B∀z∞⊗N≤J⊃j↑JR>:~B6>5Jα⎇α:,b1l4PH&↑"Lb∃αZL~R&5↓Yα:Vdaα∩<hP$$&∀*≡&9αα∞>6l*:Qiαα∪'O∞∪3∃βn{5∨Mπ;π'Qε{;MlhP$$&$JNε
d)"Z&≥"&5%Xh($$Lz2⊃αzαZ&∞$J5l4PH$&ZL~R&5¬yα>:L!j:⊗E!"Z&≥"&5%Xh($$Lz:&⊃Tr⊗bQDz2⊃%¬yα:Vdal4(HH&⊗:#X4($MαJ>∞-~N&⊃U:ε&R%JB∃"lz5%αz↓Al4PH&⊗:
*⊗V∃E∩V:F,*V∃2lz5%lhP$&⊗t!l4(L~VJJ,rQα⎇∧rV21Z↓α∞>lj⊗:QR↓β↔cεc'∂'"β∪↔πfc?∂π&)⎇l4PIr∩&≤j&NM∧b⊗Z⊗b↓EylhP&⊗:#X4(4UαJ>∞,"VJ∃¬:ε&QXh(&
,:&9↓∧~>66,rQiα≡33↔∩β←'OF+MβSzβ←π'"βW;SNaβπ3bβ∪↔O≡+;∪↔w#Mβ#∂3∃β∪O≠7'O≡+⊃l4PJJBR∩B>:&"Iα∩⊗∪X4(&L1αBJ|~⊗NNL!j∩⊗∧*:∩⊗u"M"∞-∩J⊗:"Im↓h(&RD*8&
,:&9↓∧~>66,rQi↓∧kWOQπ;π'QXh($&¬∩>∞⊗≥~&⊃j(CURRENT) ← <RETURN ADDRESS>;
		PROCESSID:WAITTYPE(CURRENT) ← 1;
		DEB ← PROCESSID:WAITONS(CURRENT);
		WHILE DEB ≠ NULL DO
			BEGIN  COMMENT:  Enable all wait ons;
			IF ONID:STATUS(DEB) LAND ENABLE = 0
			THEN	BEGIN
				ONID:STATUS(DEB) ← ONID:STATUS(DEB) LAND ¬KILL;
				PUSHJ (ONID:OPC(DEB));
				Comment:  That causes it to reschedule itself;
				END;
			DEB ← NEXT(DEB);
			END;
		<DISMISS LEVEL 1>;
		END;
	END;

PROCEDURE WAIT_ENABLE (RPTR (ONID) MON);
	BEGIN  COMMENT:  Wish to set up a wait on-monitor;
	IF ONID:NEXT(MON) = NULL 
	THEN	BEGIN  COMMENT:  Add this wait on to list for Current;
		ONID:NEXT(MON) ← PROCESSID:WAITONS(CURRENT);
		PROCESSID:WAITONS(CURRENT) ← ONID;
		END;
	END;

PROCEDURE LEVEL_ONE_INTERRUPT_HANDLER;
	BEGIN
	IF RUNQUEUE = NULL THEN
		BEGIN  COMMENT:  No one left to run;
		<CLEAR INTERRUPT>;
		<DISMISS LEVEL 1>;
		END
	ELSE	BEGIN
		CURRENT ← DEQUEUE(RUNQUEUE);
		PUSH NAME(CURRENT);
		PUSH IPC(CURRENT);
		PUSHJ INTERPRETER;
		END;
	END;

Comment:  The following are not part of scheduling;

PROCEDURE RUN_ENABLE (RPTR (ONID) MON);
	BEGIN  COMMENT:  Wish to enable a run on monitor;
	↑;
	IF ONID:STATUS(MON) LAND ENABLE ≠ 0
	THEN	BEGIN ↓; RETURN END;  COMMENT:  Already going;
	ONID:STATUS(MON) ← ONID:STATUS(MON) LAND ¬KILL;
	PUSHJ (ONID:OPC(MON));
	Comment:  This causes it to reschedule itself in future;
	END;

PROCEDURE DISABLE (RPTR(ONID) MON);
	BEGIN  
	ONID:STATUS(MON) ← KILL;
	END;

SWING-TIME Calculation of set points.

Due to the run-time modification of trajectories and sloppiness
in the compiler, trajectories will occasionally end up  requesting
joints to exceed their limits.  To avoid this calamity, the servo
will modify the set point. Each joint has two limits to its motion;
call these L1 and L2.  There will be a "warning track" close to
these limits; if the joint enters the warning track, it will be
deflected in such a way that it can never hit the limit.  The
warning tracks begin at W1 and W2.  The set point is calculated
as follows:

S ← IF S > W2 
	THEN L2 - (L2-W2)↑2/((L2-W2)+(S-W2))
    ELSE IF S < W1
	THEN L1 - (L1-W1)↑2/((L1-W1)+(S-W1))
    ELSE S


Here it is assumed that W2 is the high track, and W1 marks the low one.
Note that much of this expression is built of constants.